from django.contrib.auth.decorators import login_required
from django.http import JsonResponse, HttpResponse
from django.shortcuts import render
from django.db.models import Subquery, OuterRef, Prefetch
from django.conf import settings

from user.models import UserScore
from .models import Catalog, Resource
import os, uuid
from captcha.image import ImageCaptcha, random_color
import random, string
from django_redis import get_redis_connection


@login_required
def upload(request):
    if request.method == "GET":
        # 查询所有的资源类型( 主要查询一级 、顺带查询二级)
        #  一关联多 使用 prefetch_related
        #  多查 一 、使用 select_related
        queryset = Catalog.objects.filter(
            parent__isnull=True,
            is_delete=False
        ).prefetch_related(
            Prefetch(
                'sub_catalogs',
                queryset=Catalog.objects.filter(is_delete=False),
                to_attr='active_sub_catalogs'
            )
        )
        return render(request, "upload.html", {"catalogs": queryset})

    # 接收页面需要的参数
    name = request.POST.get("name")
    path = request.POST.get("url")
    desc = request.POST.get("descript")
    score = request.POST.get("score")
    catalog_id = request.POST.get("catalog")
    keywords = request.POST.get("keywords")
    code = request.POST.get("code")
    size = request.POST.get("size")
    ext = request.POST.get("ext")

    redis_key = f"upload:captcha:{request.user.pk}"
    redis_client = get_redis_connection()

    redis_code = redis_client.get(redis_key).decode('utf-8')

    if redis_code.upper() != code.upper():
        return JsonResponse({"code": 400, "message": "验证码错误"}, safe=False)

    # 验证码正确，删除验证码
    redis_client.delete(redis_key)
    # 保存资源
    res = Resource.objects.create(name=name, desc=desc, keywords=keywords,catalog_id=catalog_id, score=score, path=path, size=size, ext=ext, user=request.user, state="1")
    # 赠送积分
    UserScore.objects.create_score("上传", user_id=request.user.pk, remark="资源上传", res_id=res.pk)
    return JsonResponse({"code": 200, "message": "资源保存成功"}, safe=False)


@login_required
def upload_resource(request):

    # 获取上传的资源
    resource = request.FILES.get("resource")

    # 将其存储到 指定的 目录下 media/resource/ 下
    path = os.path.join(settings.MEDIA_ROOT, "resource")

    if not os.path.exists(path):
        os.makedirs(path)
    # 生成一个资源名称
    name = str(uuid.uuid4())

    with open(os.path.join(path, name), "wb") as f:
        for chunk in resource.chunks():
            f.write(chunk)

    return JsonResponse({"code": 200, "msg": "上传成功", "url": f"resource/{name}"})


@login_required
def captcha(request):
    """
    生成验证码
    """
    # 获取验证码的宽和高
    width = int(request.GET.get("w"))
    height = int(request.GET.get("h"))

    # 创建一个验证码对象 , 设置 随机的字体大小
    captcha = ImageCaptcha(width=width, height=height, font_sizes=[20, 24, 26, 28, 30])

    # 随机生成 4位长度 的 验证码字符串
    captcha_array = random.choices(string.ascii_letters + string.digits, k=4)

    captcha_chars = "".join(captcha_array)

    # 使用 captcha 生成验证码图片
    image = captcha.create_captcha_image(captcha_chars, color=(255, 0, 0), background=(255, 255, 255))

    # 给验证码图片 添加 干扰线
    captcha.create_noise_curve(image, color=random_color(100, 200))
    # 给验证码图片添加 干扰点
    captcha.create_noise_dots(image, color=random_color(100, 200), number=30)

    # 将验证码 存储到 redis 数据库中，且设置过期时间 30分钟
    redis_key = f"upload:captcha:{request.user.pk}"
    redis_client = get_redis_connection()

    redis_client.setex(redis_key, 30 * 60, captcha_chars)

    from io import BytesIO
    # 将图片 写入到 响应对象中
    # 创建一个 流对象
    out = BytesIO()
    # 存储数据到 流中
    image.save(out, format="png")
    # 将流的读取位置指向 0
    out.seek(0)
    # 以 图片的格式 返回 验证码
    return HttpResponse(out.read(), content_type="image/png")